/* -----------------------------------------------------------------------------
 * Copyright (c) 2014 ARM Ltd.
 *
 * This software is provided 'as-is', without any express or implied warranty. 
 * In no event will the authors be held liable for any damages arising from 
 * the use of this software. Permission is granted to anyone to use this 
 * software for any purpose, including commercial applications, and to alter 
 * it and redistribute it freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not 
 *    claim that you wrote the original software. If you use this software in
 *    a product, an acknowledgment in the product documentation would be 
 *    appreciated but is not required. 
 * 
 * 2. Altered source versions must be plainly marked as such, and must not be 
 *    misrepresented as being the original software. 
 * 
 * 3. This notice may not be removed or altered from any source distribution.
 *   
 *
 * $Date:        15. April 2014
 * $Revision:    V1.00
 *  
 * Project:      Flash Programming Functions for STMicroelectronics STM32F4xx Flash
 * --------------------------------------------------------------------------- */

/* History:
 *  Version 1.00
 *    Initial release
 */

#include "FlashOS.H" // FlashOS Structures

#include <stdint.h>
#include <string.h>

#include "main.h"
#include "octospi.h"
#include "gpio.h"
#include "w25q128jv.h"

extern void SystemClock_Config(void);

HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
    return HAL_OK;
}

void HAL_Delay(uint32_t Delay)
{
    volatile int i=0;
    for (i=0; i<0x1000; i++);
}

uint32_t HAL_GetTick(void)
{
    volatile int i;
    for (i=0; i < 512; i++);
    uwTick++;
    return uwTick;
}

/*
 *  Initialize Flash Programming Functions
 *    Parameter:      adr:  Device Base Address
 *                    clk:  Clock Frequency (Hz)
 *                    fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
 *    Return Value:   0 - OK,  1 - Failed
 */
uint32_t base_adr = 0;
int Init(unsigned long adr, unsigned long clk, unsigned long fnc)
{
  base_adr = adr;

  //uint8_t id[2];
  //HAL_MPU_Disable();
  //SCB_DisableDCache();
  //SCB_DisableICache();
  SystemInit();
  HAL_Init();
  //SystemClock_Config();
  //MX_GPIO_Init();
  MX_OCTOSPI1_Init();
  //OSPI_W25Q128JV_DeviceID(id);
  //if (id[0] == 0xef && id[1] == 0x17)
  //{
  //    HAL_GPIO_TogglePin(RGB_R_GPIO_Port, RGB_R_Pin);
  //}
  OSPI_W25Q128JV_Reset();
  OSPI_W25Q128JV_EnableMemoryMappedMode();
  return (0);
}

/*
 *  De-Initialize Flash Programming Functions
 *    Parameter:      fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
 *    Return Value:   0 - OK,  1 - Failed
 */

int UnInit(unsigned long fnc)
{
  //HAL_OSPI_MspDeInit(&hospi1);
  //MX_OCTOSPI1_Init();
  //OSPI_W25Q128JV_Reset();
  //OSPI_W25Q128JV_EnableMemoryMappedMode();
  return (0);
}

/*
 *  Erase complete Flash Memory
 *    Return Value:   0 - OK,  1 - Failed
 */

int EraseChip(void)
{
  //HAL_OSPI_MspDeInit(&hospi1);
  //MX_OCTOSPI1_Init();
  //OSPI_W25Q128JV_Reset();
  return (1);
  //OSPI_W25Q128JV_CHIP_ERASE();
  //for (volatile uint32_t i = 0; i < 999999; i++)
  //{
  //    ;
  //}
  //OSPI_W25Q128JV_EnableMemoryMappedMode();
  //return (0);
}

/*
 *  Erase Sector in Flash Memory
 *    Parameter:      adr:  Sector Address
 *    Return Value:   0 - OK,  1 - Failed
 */

int EraseSector(unsigned long adr)
{
  HAL_OSPI_MspDeInit(&hospi1);
  MX_OCTOSPI1_Init();
  OSPI_W25Q128JV_Reset();
  if (OSPI_W25Q128JV_ERASE_Block64K(adr - base_adr) != OSPI_OK)
  {
    return (1);
  }
  OSPI_W25Q128JV_EnableMemoryMappedMode();
  return (0);
}

/*
 *  Program Page in Flash Memory
 *    Parameter:      adr:  Page Start Address
 *                    sz:   Page Size
 *                    buf:  Page Data
 *    Return Value:   0 - OK,  1 - Failed
 */

int ProgramPage(unsigned long adr, unsigned long sz, unsigned char *buf)
{
  HAL_OSPI_MspDeInit(&hospi1);
  MX_OCTOSPI1_Init();
  OSPI_W25Q128JV_Reset();
    
  if (OSPI_W25Q128JV_Write(buf, adr - base_adr, sz) != OSPI_OK)
  {
    return (1);
  }
  OSPI_W25Q128JV_EnableMemoryMappedMode();
  return (0);
}

#if 1
unsigned long Verify(unsigned long adr, unsigned long sz, unsigned char *buf)
{
  uint8_t *p = (uint8_t *)adr;

  for (int i = 0; i < sz; i++)
  {
    if (*p != buf[i])
    {
      return ((unsigned long)p);
    }
    p++;
  }

  return (adr + sz);
}
#endif
